module data_drive (input			wire						vga_clk,
                input			wire						rst_n,
                input			wire						clk,
                input			wire		[ 11:0 ]		addr_h,
                input			wire		[ 11:0 ]		addr_v,
                input			wire		[ 2:0 ]		key,
                input			wire   				   rx1,
                input			wire   				   rx2,
                input			wire  				   rx3,
                input			wire  				   rx4,
                input			wire  				   rx5,
                input			wire  				   rx6,
                input			wire  				   rx7,
                input			wire  				   rx8,
                output			reg		[ 23:0 ]				rgb_data);
    
   

    localparam orange = 24'd16750899;   // 11111100_11111111_00001000
    localparam yellow = 24'd16776960;   // 11111111_11111111_10000000
    localparam green  = 24'd65280;      // 00111111_11111111_00000000
    localparam blue   = 24'd255;        // 00000001_11111111_00000000
    localparam indigo = 24'd10027161;    // 01111100_10000000_00000000
    localparam purple = 24'd16738047;      // 00001111_11111111_00000000
    localparam white  = 24'd16777215;   // 11111111_11111111_11111111
    localparam black  = 24'd0;          // 00000000_00000000_00000000
    localparam red    = 24'd16711936;   // 11111111_11111111_11110000


    // 分辨率为 640*480 时行时序各个参数定义
    parameter       C_H_SYNC_PULSE      =   96  , 
                    C_H_BACK_PORCH      =   48  ,
                    C_H_ACTIVE_TIME     =   640 ,
                    C_H_FRONT_PORCH     =   16  ,
                    C_H_LINE_PERIOD     =   800 ;

    // 分辨率为 640*480 时场时序各个参数定义
    parameter       C_V_SYNC_PULSE      =   2   , 
                    C_V_BACK_PORCH      =   33  ,
                    C_V_ACTIVE_TIME     =   480 ,
                    C_V_FRONT_PORCH     =   10  ,
                    C_V_FRAME_PERIOD    =   525 ;



    
    localparam	states_1 = 1; // 欢迎
    localparam	states_2 = 2; // 高速
    localparam	states_3 = 3; // 低速
	 localparam	states_4 = 4; // 泊车
	 localparam	states_5 = 5; // 前方有障碍物
	 localparam	states_6 = 6; // 后方有障碍物
	 localparam	states_7 = 7; // 左侧有障碍物
	 localparam	states_8 = 8; // 右侧有障碍物
	 
    parameter	height = 239; // 图片1高度
    parameter	width  = 400; // 图片1宽度
    parameter	height2 = 100; // 图片2高度
    parameter	width2  = 400; // 图片2宽度
    parameter	height3 = 100; // 图片3高度
    parameter	width3  = 400; // 图片3宽度
	 parameter	height4 = 100; // 图片4高度
    parameter	width4  = 400; // 图片4宽度
	 parameter	height5 = 100; // 图片5高度
    parameter	width5  = 400; // 图片5宽度
	 parameter	height6 = 100; // 图片6高度
    parameter	width6  = 400; // 图片6宽度
	 parameter	height7 = 100; // 图片7高度
    parameter	width7  = 400; // 图片7宽度
	 parameter	height8 = 100; // 图片8高度
    parameter	width8  = 400; // 图片8宽度
	 
    reg			[ 3:0 ]			states_current			; // 当前状态
    reg			[ 3:0 ]			states_next			    ; // 下个状态
	 
    reg			[ 17:0 ]		rom_address				; // ROM1地址
	 reg			[ 17:0 ]		rom_address2				; // ROM2地址
	 reg			[ 17:0 ]		rom_address3				; // ROM3地址
	 reg			[ 17:0 ]		rom_address4				; // ROM4地址
	 reg			[ 17:0 ]		rom_address5				; // ROM5地址
	 reg			[ 17:0 ]		rom_address_below				; // ROM_below地址
	 reg			[ 17:0 ]		rom_address_left				; // ROM_left地址
	 reg			[ 17:0 ]		rom_address_right				; // ROM_right地址
	 
    wire			[ 23:0 ]		rom_data				; // 图片数据
	 wire			[ 23:0 ]		rom_data2				; // 图片2数据
	 wire			[ 23:0 ]		rom_data3				; // 图片3数据
	 wire			[ 23:0 ]		rom_data4				; // 图片4数据
	 wire			[ 23:0 ]		rom_data5				; // 图片5数据
	 wire			[ 23:0 ]		rom_data_below				; // 图片6数据
	 wire			[ 23:0 ]		rom_data_left				; // 图片7数据
	 wire			[ 23:0 ]		rom_data_right 			; // 图片8数据
	 
    wire							flag_enable_out1			; // 图片1有效区域
    wire							flag_enable_out2			; // 图片2有效区域
	 wire							flag_enable_out3			; // 图片3有效区域
	 wire							flag_enable_out4			; // 图片4有效区域
	 wire							flag_enable_out5			; // 图片5有效区域
	 wire							flag_enable_out_below			; // 图片6有效区域
	 wire							flag_enable_out_left			; // 图片7有效区域
	 wire							flag_enable_out_right			; // 图片8有效区域
	 
	 
    wire							flag_clear_rom_address		; // 地址清零
	 wire							flag_clear_rom_address2		; // 地址2清零
	 wire							flag_clear_rom_address3		; // 地址3清零
	 wire							flag_clear_rom_address4		; // 地址4清零
	 wire							flag_clear_rom_address5		; // 地址5清零
	 wire							flag_clear_rom_address_below		; // 地址6清零
	 wire							flag_clear_rom_address_left		; // 地址7清零
	 wire							flag_clear_rom_address_right		; // 地址8清零
	 
    wire							flag_begin_h			    ; // 图片1显示行
    wire							flag_begin_v			    ; // 图片1显示列
	 wire							flag_begin_h2			    ; // 图片2显示行
    wire							flag_begin_v2			    ; // 图片2显示列
	 wire							flag_begin_h3			    ; // 图片3显示行
    wire							flag_begin_v3			    ; // 图片3显示列
	 wire							flag_begin_h4			    ; // 图片4显示行
    wire							flag_begin_v4			    ; // 图片4显示列
	 wire							flag_begin_h5			    ; // 图片5显示行
    wire							flag_begin_v5			    ; // 图片5显示列

	 wire							flag_begin_h6			    ; // 图片6显示行
    wire							flag_begin_v6			    ; // 图片6显示列
	 
	 wire							flag_begin_h7			    ; // 图片7显示行
    wire							flag_begin_v7			    ; // 图片7显示列
	 
	 wire							flag_begin_h8			    ; // 图片8显示行
    wire							flag_begin_v8			    ; // 图片8显示列
	 




    //状态转移
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            states_current <= states_1;
        end
        else begin
            states_current <= states_next;
        end
    end
	 
    //状态判断
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            states_next <= states_1;
        end
        else if (rx1) begin
            states_next <= states_1;		
        end else if (rx2) begin
            states_next <= states_2; 
            end
            else if (rx3) begin
            states_next <= states_3; 
            end
            else if (rx4) begin
            states_next <= states_4;
            end
        else begin
            states_next <= states_next;
        end
    end





    reg    [30-1:0]    cnt_4s     ; 
    wire   end_cnt_4s ; 
    always @(posedge clk or negedge rst_n) 
        if (!rst_n )
            cnt_4s  <= 30'b0;
		else if (end_cnt_4s)
            cnt_4s  <= 30'b0;
        else if (rx5 || rx6 || rx7 || rx8 )
            cnt_4s <= 30'b1;
        else if (cnt_4s)
                cnt_4s  <= cnt_4s  + 1'd1;
        else 
            cnt_4s  <= cnt_4s ;

    assign end_cnt_4s  = (cnt_4s >= 100_000_000- 1);

    reg [5:0] show_temp = 6'b0;


always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) 
            show_temp <= 0;
        else if ( end_cnt_4s )
            show_temp <= 0;
        else if (rx5)
            show_temp <= 6'd5;
        else if (rx6)
            show_temp <= 6'd6;
        else if (rx7)
            show_temp <= 6'd7;
        else if (rx8)
            show_temp <= 6'd8;
        else 
            show_temp <= show_temp;
    end







    //状态输出
    always @( * ) begin



        if (show_temp)

                    case (show_temp)
                        6'd5:
                            rgb_data = rom_data5;
                        6'd6:
                            rgb_data = rom_data_below;
                        6'd7:
                            rgb_data = rom_data_left;
                        6'd8:
                            rgb_data = rom_data_right;
                        default: 
                        rgb_data = white;
                    endcase

        else 

        begin

        case ( states_current )
            states_1 : begin
               if ( flag_enable_out1 ) begin
                    rgb_data = rom_data;//显示第一张图片
                end
                else begin
                    rgb_data = black;
                end      
            end
            states_2 : begin
                if ( flag_enable_out2 ) begin
                    rgb_data = rom_data2;//显示第二张图片
                end
                else begin
                    rgb_data = black;
                end
            end
            states_3 : begin
                if ( flag_enable_out3 ) begin
                    rgb_data = rom_data3;
                end
                else begin
                    rgb_data = black;
                end
                
            end
				states_4 : begin
                if ( flag_enable_out4 ) begin
                    rgb_data = rom_data4;
                end
                else begin
                    rgb_data = black;
                end
            
            end
		
            default: begin
                case ( addr_h )
                    0 : rgb_data      = black;
                    1 : rgb_data      = red;
                    81 : rgb_data     = orange;
                    161: rgb_data     = yellow;
                    241: rgb_data     = green;
                    321: rgb_data     = blue;
                    401: rgb_data     = indigo;
                    481: rgb_data     = purple;
                    561: rgb_data     = white;
                    default: rgb_data = rgb_data;
                endcase
            end
        endcase

        end

    end

    assign flag_begin_h     = addr_h > ( ( 640 - width ) / 2 ) && addr_h < ( ( 640 - width ) / 2 ) + width + 1;
    assign flag_begin_v     = addr_v > ( ( 480 - height )/2 ) && addr_v <( ( 480 - height )/2 ) + height + 1;
    assign flag_enable_out1 = states_current == states_1 && flag_begin_h && flag_begin_v;
    
	 assign flag_begin_h2     = addr_h > ( ( 640 - width2 ) / 2 ) && addr_h < ( ( 640 - width2 ) / 2 ) + width2 + 1;
    assign flag_begin_v2     = addr_v > ( ( 480 - height2 )/2 ) && addr_v <( ( 480 - height2 )/2 ) + height2 + 1;
    assign flag_enable_out2 = states_current == states_2 && flag_begin_h2 && flag_begin_v2;
	 
	 assign flag_begin_h3     = addr_h > ( ( 640 - width3 ) / 2 ) && addr_h < ( ( 640 - width3 ) / 2 ) + width3 + 1;
    assign flag_begin_v3     = addr_v > ( ( 480 - height3 )/2 ) && addr_v <( ( 480 - height3 )/2 ) + height3 + 1;
	 assign flag_enable_out3 = states_current == states_3 && flag_begin_h3 && flag_begin_v3;
	 
	 assign flag_begin_h4     = addr_h > ( ( 640 - width4 ) / 2 ) && addr_h < ( ( 640 - width4 ) / 2 ) + width4 + 1;
    assign flag_begin_v4     = addr_v > ( ( 480 - height4 )/2 ) && addr_v <( ( 480 - height4 )/2 ) + height4 + 1;
	 assign flag_enable_out4 = states_current == states_4 && flag_begin_h4 && flag_begin_v4;
	 
	 assign flag_begin_h5     = addr_h > ( ( 640 - width5 ) / 2 ) && addr_h < ( ( 640 - width5 ) / 2 ) + width5 + 1;
    assign flag_begin_v5     = addr_v > ( ( 480 - height5 )/2 ) && addr_v <( ( 480 - height5 )/2 ) + height5 + 1;
	 assign flag_enable_out5 =  flag_begin_h5 && flag_begin_v5;
	 
	 assign flag_begin_h6     = addr_h > ( ( 640 - width6 ) / 2 ) && addr_h < ( ( 640 - width6 ) / 2 ) + width6 + 1;
    assign flag_begin_v6     = addr_v > ( ( 480 - height6 )/2 ) && addr_v <( ( 480 - height6 )/2 ) + height6 + 1;
	 assign flag_enable_out_below =  flag_begin_h6 && flag_begin_v6;
	 
	 assign flag_begin_h7     = addr_h > ( ( 640 - width7 ) / 2 ) && addr_h < ( ( 640 - width7 ) / 2 ) + width7 + 1;
    assign flag_begin_v7     = addr_v > ( ( 480 - height7 )/2 ) && addr_v <( ( 480 - height7 )/2 ) + height7 + 1;
	 assign flag_enable_out_left =  flag_begin_h7 && flag_begin_v7;
	 
	 assign flag_begin_h8     = addr_h > ( ( 640 - width8 ) / 2 ) && addr_h < ( ( 640 - width8 ) / 2 ) + width8 + 1;
    assign flag_begin_v8     = addr_v > ( ( 480 - height8 )/2 ) && addr_v <( ( 480 - height8 )/2 ) + height8 + 1;
	 assign flag_enable_out_right =  flag_begin_h8 && flag_begin_v8;
    //ROM地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address <= 0;
        end
        else if ( flag_clear_rom_address  ||  key[ 0 ]|| rx1 ) begin //计数满清零
            rom_address <= 0;
        end
            else if ( flag_enable_out1 ) begin  //在有效区域内+1
            rom_address <= rom_address + 1;
            end
        else begin  //无效区域保持
            rom_address <= rom_address;
        end
    end
    assign flag_clear_rom_address = rom_address == height * width - 1;
	 
	 //ROM2地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address2 <= 0;
        end
        else if ( flag_clear_rom_address2  ||  key[ 1 ] || rx2) begin //计数满清零
            rom_address2 <= 0;
        end
            else if ( flag_enable_out2 ) begin  //在有效区域内+1
            rom_address2 <= rom_address2 + 1;
            end
        else begin  //无效区域保持
            rom_address2 <= rom_address2;
        end
    end
    assign flag_clear_rom_address2 = rom_address2 == height2 * width2 - 1;
  
   //ROM3地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address3 <= 0;
        end
        else if ( flag_clear_rom_address3  ||  key[2] ||rx3 ) begin //计数满清零
            rom_address3 <= 0;
        end
            else if ( flag_enable_out3 ) begin  //在有效区域内+1
            rom_address3 <= rom_address3 + 1;
            end
        else begin  //无效区域保持
            rom_address3 <= rom_address3;
        end
    end
    assign flag_clear_rom_address3 = rom_address3 == height3 * width3 - 1;
	 
	 //ROM4地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address4 <= 0;
        end
        else if ( flag_clear_rom_address4  || rx4 ) begin //计数满清零
            rom_address4 <= 0;
        end
            else if ( flag_enable_out4 ) begin  //在有效区域内+1
            rom_address4 <= rom_address4 + 1;
            end
        else begin  //无效区域保持
            rom_address4 <= rom_address4;
        end
    end
    assign flag_clear_rom_address4 = rom_address4 == height4 * width4 - 1;
	 
	 	 //ROM5地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address5 <= 0;
        end
        else if ( flag_clear_rom_address5  || rx5 ) begin //计数满清零
            rom_address5 <= 0;
        end
            else if ( flag_enable_out5 ) begin  //在有效区域内+1
            rom_address5 <= rom_address5 + 1;
            end
        else begin  //无效区域保持
            rom_address5 <= rom_address5;
        end
    end
    assign flag_clear_rom_address5 = rom_address5 == height5 * width5 - 1;
	 
	  	 //ROM6地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address_below <= 0;
        end
        else if ( flag_clear_rom_address_below  || rx6 ) begin //计数满清零
            rom_address_below <= 0;
        end
            else if ( flag_enable_out_below ) begin  //在有效区域内+1
            rom_address_below <= rom_address_below + 1;
            end
        else begin  //无效区域保持
            rom_address_below <= rom_address_below;
        end
    end
    assign flag_clear_rom_address_below = rom_address_below == height6 * width6 - 1;
	 
	 //ROM7地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address_left <= 0;
        end
        else if ( flag_clear_rom_address_left || rx7 ) begin //计数满清零
            rom_address_left <= 0;
        end
            else if ( flag_enable_out_left ) begin  //在有效区域内+1
            rom_address_left <= rom_address_left + 1;
            end
        else begin  //无效区域保持
            rom_address_left <= rom_address_left;
        end
    end
    assign flag_clear_rom_address_left = rom_address_left == height7 * width7 - 1;
	 
	 	 //ROM8地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address_right <= 0;
        end
        else if ( flag_clear_rom_address_right || rx8 ) begin //计数满清零
            rom_address_right <= 0;
        end
            else if ( flag_enable_out_right ) begin  //在有效区域内+1
            rom_address_right <= rom_address_right + 1;
            end
        else begin  //无效区域保持
            rom_address_right <= rom_address_right;
        end
    end
    assign flag_clear_rom_address_right = rom_address_right == height8 * width8 - 1;
	 
    //实例化ROM
    ROM1	ROM1_inst (
    .address ( rom_address ),
    .clock ( vga_clk ),
    .q ( rom_data )
    );
	     //实例化ROM
    ROM2	ROM2_inst (
    .address ( rom_address2 ),
    .clock ( vga_clk ),
    .q ( rom_data2 )
    );
	      //实例化ROM
    ROM3	ROM3_inst (
    .address ( rom_address3 ),
    .clock ( vga_clk ),
    .q ( rom_data3 )
    );
	       //实例化ROM
    ROM4	ROM4_inst (
    .address ( rom_address4 ),
    .clock ( vga_clk ),
    .q ( rom_data4 )
    );
	        //实例化ROM
    ROM5	ROM5_inst (
    .address ( rom_address5 ),
    .clock ( vga_clk ),
    .q ( rom_data5 )
    );
	         //实例化ROM
    ROM_BELOW	ROM_BELOW_inst (
    .address ( rom_address_below ),
    .clock ( vga_clk ),
    .q ( rom_data_below )
    );
	 	         //实例化ROM
    ROM_left	ROM_left_inst (
    .address ( rom_address_left ),
    .clock ( vga_clk ),
    .q ( rom_data_left )
    );
	 	 	         //实例化ROM
    ROM_right	ROM_right_inst (
    .address ( rom_address_right ),
    .clock ( vga_clk ),
    .q ( rom_data_right )
    );
	 
endmodule // data_drive